/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package astroLib;

import java.io.IOException;


/**
 *
 * @author mehmetrg
 */
public class SunSet {


private static Equatorial result;

static final double	 Rad       = Math.PI / 180.0;




//------------------------------------------------------------------------------
//
// SinAlt: Sine of the altitude of Sun or Moon
//
// Input:
//
//   Event     Indicates event to find
//   MJD0      0h at date to investigate (as Modified Julian Date)
//   Hour      Hour
//   lambda    Geographic east longitude in [rad]
//   Cphi      Cosine of geographic latitude
//   Sphi      Sine of geographic latitude
//
// <return>:   Sine of the altitude of Sun or Moon at instant of Event
//*BU*
//------------------------------------------------------------------------------
static double SinAlt ( int Event, double MJD0, double Hour,
                double lambda, double Cphi, double Sphi )
{
  //
  // Variables
  //
  double  MJD, T, RA, Dec, tau;
  int   Moon    =0;

  MJD = MJD0 + Hour/24.0;
  T   = (MJD-51544.5)/36525.0;

 if (Event==Moon)
  {
      APC_Moon moonData= new APC_Moon();
      result=moonData.MiniMoon(T);
  }

  else
     {
      APC_Sun sunData= new APC_Sun();
      result=sunData.MiniSun(T);
  }


  tau = APC_Time.GMST(MJD) + lambda - result.RA;

  return ( Sphi*Math.sin(result.Dec)+Cphi*Math.cos(result.Dec)*Math.cos(tau) );
}

//------------------------------------------------------------------------------
//
// FindEvents: Search for rise/set/twilight events of Sun or Moon
//
// Input:
//
//   Event     Indicates event to search for
//   MJD0h     0h at desired date as Modified Julian Date
//   lambda    Geographic east longitude of the observer in [rad]
//   phi       Geographic latitude of the observer in [rad]
//
// Output:
//
//   LT_Rise   Local time of rising or beginning of twilight
//   LT_Set    Local time of setting or end of twilight
//   rises     Event takes place
//   sets      Event takes place
//   above     Sun or Moon is circumpolar
//
//------------------------------------------------------------------------------
static RiseSetStatus FindEvents ( int Event, double MJD0h, double lambda, double phi)
{
  //
  // Constants
  //

  double[] sinh0 = {
   Math.sin(Rad*( +8.0/60.0)), // Moonrise              at h= +8'
   Math.sin(Rad*(-50.0/60.0)), // Sunrise               at h=-50'
   Math.sin(Rad*(- 6.0 )), // Civil twilight        at h=-6 deg
   Math.sin(Rad*(-12.0)), // Nautical twilight     at h=-12deg
   Math.sin(Rad*(-18.0)), // Astronomical twilight at h=-18deg
  };
  RiseSetStatus rss=new RiseSetStatus();
  double Cphi =Math.cos(phi);
  double Sphi =Math.sin(phi);


  //
  // Variables
  //
  double hour = 1.0;
  double y_minus, y_0, y_plus;
  double xe, ye, root1, root2;
  int nRoot;


  // Initialize for search
  y_minus = SinAlt(Event, MJD0h, hour-1.0, lambda, Cphi, Sphi)-sinh0[Event];

  rss.above = (y_minus>0.0);
  rss.rises = false;
  rss.sets  = false;


  // loop over search intervals from [0h-2h] to [22h-24h]
  do {

    y_0    = SinAlt( Event, MJD0h, hour    , lambda, Cphi, Sphi )-sinh0[Event];
    y_plus = SinAlt( Event, MJD0h, hour+1.0, lambda, Cphi, Sphi )-sinh0[Event];

    // find parabola through three values y_minus,y_0,y_plus
    double[] quadOut=APC_Math.Quad (y_minus,y_0,y_plus);
     xe=quadOut[0]; ye=quadOut[1]; root1=quadOut[2]; root2=quadOut[3];
     nRoot= (int)quadOut[4];
    if ( nRoot==1 ) {
      if ( y_minus < 0.0 )
        { rss.LT_Rise = hour+root1;  rss.rises = true; }
      else
        { rss.LT_Set  = hour+root1;  rss.sets  = true; }
    }

    if ( nRoot == 2 ) {
      if ( ye < 0.0 )
        { rss.LT_Rise = hour+root2;  rss.LT_Set = hour+root1; }
      else
        { rss.LT_Rise = hour+root1;  rss.LT_Set = hour+root2; }
      rss.rises = true; rss.sets = true;
    }

    y_minus = y_plus;     // prepare for next interval
    hour += 2.0;

  }
  while ( !( ( hour == 25.0 ) || ( rss.rises && rss.sets ) ) );
  return rss;
}

  public static void main(String[] args) throws IOException {
        // TODO code application logic here
    int   Sun     =1;
     int   AstroTwi=4;  // indicates astronomical twilight
    System.out.println("      SUNSET: solar and lunar rising and setting times  " );
    System.out.println( "        (c) 1999 Oliver Montenbruck, Thomas Pfleger     " );
   // BufferedReader reader =new BufferedReader(new InputStreamReader(System.in));
   // System.out.print("ENTER Date: For Example 2008 02 25:");
   // String dateStr = reader.readLine();

   // boolean  above, rise, sett;
    RiseSetStatus riseSetStatus;
    int      iEvent, day;
    double   lambda, zone, phi;
    double   date, start_date, LT_Rise, LT_Set;
    int  Event, Twilight;
    System.out.println( "    Date             Moon              Sun             Twilight " );
    System.out.println( "                  rise/set          rise/set        beginning/end" );
    //year=2008;month=2;day=25;
    lambda=Rad*32;
    phi=Rad*39;
    zone=2/24.0;
    Twilight=AstroTwi;
    start_date =APC_Time.Mjd(2008,02,25,0,0,0) - zone;

    // loop over 10 subsequent days
    for (day=0; day<10; day++) {

    // current date
    date = start_date + day;
    System.out.println(APC_Time.DateTime(date+zone));

    riseSetStatus=FindEvents (Sun, date, lambda, phi);
    //System.out.println( "MoonRise  "+APC_Time.Time(riseSetStatus.LT_Rise)+" "+APC_Time.Time(riseSetStatus.LT_Set));
    //System.out.print("   MoonSet );
    // loop over cases (Moon, Sun, Twilight)
/*   for (
            )
   {

       // After events for Moon and Sun: specify kind of twilight event
Event.
       Event= (iEvent<2) ? Event : Twilight;


      // Now try to find times of events



      // Output
      if ( rise || sett )  {
        if ( rise )
          System.out.println( APC_Time.Time(LT_Rise));
        else
         System.out.println( "   ----- ");
        if ( sett )
         System.out.println(APC_Time.Time(LT_Set));
        else
         System.out.println("   ----- ");
      }
      else
        if ( above ) {
          if ( Event.ordinal()>=enEvent.CivilTwi.ordinal())
            System.out.println("    always bright ");
          else
           System.out.println( "   always visible ");
        }
        else {
          if ( Event.ordinal()>=enEvent.CivilTwi.ordinal() )
            System.out.println("     always dark  ");
          else
            System.out.println("  always invisible");
        }

    }

  }*/
  // Trailer

}
  }
}


